﻿using System;

public sealed class Indexable<TIndex, T>
{
    private readonly Func<TIndex, T> _getter;
    private readonly Action<TIndex, T> _setter;

    public Indexable(Func<TIndex, T> getter, Action<TIndex, T> setter = null)
    {
        _getter = getter;
        _setter = setter;
    }

    public T this[TIndex index]
    {
        get
        {
            return _getter(index);
        }
        set
        {
            if (_setter == null)
                throw new InvalidOperationException();
            _setter(index, value);
        }
    }
}
public sealed class Indexable<TIndex1, TIndex2, T>
{
    private readonly Func<TIndex1, TIndex2, T> _getter;
    private readonly Action<TIndex1, TIndex2, T> _setter;

    public Indexable(Func<TIndex1, TIndex2, T> getter, Action<TIndex1, TIndex2, T> setter = null)
    {
        _getter = getter;
        _setter = setter;
    }

    public T this[TIndex1 index1, TIndex2 index2]
    {
        get
        {
            return _getter(index1, index2);
        }
        set
        {
            if (_setter == null)
                throw new InvalidOperationException();
            _setter(index1, index2, value);
        }
    }
}
public sealed class Indexable<TIndex1, TIndex2, TIndex3, T>
{
    private readonly Func<TIndex1, TIndex2, TIndex3, T> _getter;
    private readonly Action<TIndex1, TIndex2, TIndex3, T> _setter;

    public Indexable(Func<TIndex1, TIndex2, TIndex3, T> getter, Action<TIndex1, TIndex2, TIndex3, T> setter = null)
    {
        _getter = getter;
        _setter = setter;
    }

    public T this[TIndex1 index1, TIndex2 index2, TIndex3 index3]
    {
        get
        {
            return _getter(index1, index2, index3);
        }
        set
        {
            if (_setter == null)
                throw new InvalidOperationException();
            _setter(index1, index2, index3, value);
        }
    }
}